{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# South Korea Qiskit Hackathon'20 - Qiskit Metal exercise\n",
    "\n",
    "## Preparation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%load_ext autoreload\n",
    "%autoreload 2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Make sure to have the right kernel selected!*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import qiskit_metal as metal\n",
    "from qiskit_metal import designs, draw\n",
    "from qiskit_metal import MetalGUI, Dict, open_docs\n",
    "\n",
    "%metal_heading Welcome to Qiskit Metal!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Welcome to Qiskit Metal! \n",
    "\n",
    "For this example tutorial, we will attempt to create a simple two qubit chip. We will want to generate the layout, simulate/analyze and tune the chip to hit the parameters we are wanting, finally rendering to a GDS file.\n",
    "\n",
    "One could generate subsections of the layout and tune individual components first, but in this case we will create all of the layout. We will want a transmon (in this case choosing ones with charge lines), meandered and simple transmission lines, capacitor couplers, and launchers for wirebond connections. So we will import these, and also create a design instance and launch the GUI."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Design the layout"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit_metal.qlibrary.qubits.transmon_pocket_cl import TransmonPocketCL\n",
    "\n",
    "from qiskit_metal.qlibrary.tlines.meandered import RouteMeander\n",
    "from qiskit_metal.qlibrary.tlines.pathfinder import RoutePathfinder\n",
    "\n",
    "from qiskit_metal.qlibrary.lumped.cap_3_interdigital import Cap3Interdigital\n",
    "from qiskit_metal.qlibrary.terminations.launchpad_wb import LaunchpadWirebond"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "design = metal.designs.DesignPlanar()\n",
    "gui = metal.MetalGUI(design)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Since we are likely to be making many changes while tuning and modifying our design, we will enable overwriting. We can also check all of the chip properties to see if we want to change the size or any other parameter."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "design.overwrite_enabled = True\n",
    "design.chips.main"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We will add the two qubits. We know we will want each qubit to have two connection pads, one for readout, and another for the connection to the other qubit. We can see any options the qubit qcomponent has to figure out what we might want to modify when creating the component. This will include the components default options (which the component designer included) as well as renderer options (which are added based on what renderers are present in Metal)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "TransmonPocketCL.get_template_options(design)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We will then add those two qubits with the options we are wanting to define, these can all be modified easily later too.\n",
    "The rebuild command is included so the changes can be seen immediately in the GUI."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "options =  dict(\n",
    "    pad_width = '425 um', \n",
    "    pocket_height = '650um',\n",
    "    cl_pocket_edge = '180',\n",
    "    connection_pads=dict(\n",
    "        readout = dict(loc_W=+1, loc_H=+1),\n",
    "        bus = dict(loc_W=-1, loc_H=-1, )\n",
    "    ))\n",
    "        \n",
    "Q1 = TransmonPocketCL(design,'Q1', options = dict(\n",
    "        pos_x='0.7mm', \n",
    "        pos_y='0mm', \n",
    "        gds_cell_name ='FakeJunction_01',\n",
    "        hfss_inductance ='14nH',\n",
    "        **options))\n",
    "\n",
    "Q2 = TransmonPocketCL(design,'Q2', options = dict(\n",
    "        pos_x='-0.7mm', \n",
    "        pos_y='0mm', \n",
    "        gds_cell_name ='FakeJunction_02',\n",
    "        hfss_inductance ='12nH',\n",
    "        orientation = '180',\n",
    "        **options))\n",
    "\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We will next connect the two transmons together to form a bus using RoutePathfinder, an auto drawing CPW transmission line. We simply have to give the start and end location using the component pins of what we are trying to connect to.\n",
    "We can use the GUI to confirm the pin names we want to give as inputs.\n",
    "\n",
    "Pins also play an important role with rendering and simulations, as any unconnected pin can be defined as a short, open, or driven terminal."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "bus_Q1_Q2 = RoutePathfinder(design, 'Bus_Q1_Q2', options = dict(\n",
    "                                            fillet='99um',\n",
    "                                            lead=dict(end_straight='250um'),\n",
    "                                            pin_inputs=Dict(\n",
    "                                                start_pin=Dict(\n",
    "                                                    component='Q1',\n",
    "                                                    pin='bus'),\n",
    "                                                end_pin=Dict(\n",
    "                                                    component='Q2',\n",
    "                                                    pin='bus')\n",
    "                                            )))\n",
    "\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Then the readout structures can be added, being the capacitor couplers and meandered transmission lines to form the readout resonators. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cap_Q1 = Cap3Interdigital(design, 'Cap_Q1', options= dict(pos_x='2.5mm', pos_y='0.25mm', orientation='90', finger_length = '40um'))\n",
    "cap_Q2 = Cap3Interdigital(design, 'Cap_Q2', options= dict(pos_x='-2.5mm', pos_y='-0.25mm', orientation='-90', finger_length = '40um'))\n",
    "\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "readout_Q1 = RouteMeander(design,'Readout_Q1', options = dict( \n",
    "                                            pin_inputs=Dict(\n",
    "                                                start_pin=Dict(\n",
    "                                                    component='Q1',\n",
    "                                                    pin='readout'),\n",
    "                                                end_pin=Dict(\n",
    "                                                    component='Cap_Q1',\n",
    "                                                    pin='a')\n",
    "                                            ),\n",
    "                                            lead=Dict(\n",
    "                                                start_straight='0.325mm',\n",
    "                                                end_straight = '125um'#put jogs here\n",
    "                                            ),\n",
    "                                            meander=Dict(\n",
    "                                                asymmetry = '-50um'),\n",
    "                                            fillet = \"99um\",\n",
    "                                            total_length = '5mm'))\n",
    "\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "readout_Q2 = RouteMeander(design,'Readout_Q2', options = dict( \n",
    "                                            pin_inputs=Dict(\n",
    "                                                start_pin=Dict(\n",
    "                                                    component='Q2',\n",
    "                                                    pin='readout'),\n",
    "                                                end_pin=Dict(\n",
    "                                                    component='Cap_Q2',\n",
    "                                                    pin='a')\n",
    "                                            ),\n",
    "                                            lead=Dict(\n",
    "                                                start_straight='0.325mm',\n",
    "                                                end_straight = '125um'#put jogs here\n",
    "                                            ),\n",
    "                                            meander=Dict(\n",
    "                                                asymmetry = '-50um'),\n",
    "                                            fillet = \"99um\",\n",
    "                                            total_length = '6mm'))\n",
    "\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "With the launchers and short transmission lines to connect them to the capacitors and the charge lines."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "launch_Q1_read = LaunchpadWirebond(design, 'Launch_Q1_Read', options = dict(pos_x = '3.5mm', orientation = '180'))\n",
    "launch_Q2_read = LaunchpadWirebond(design, 'Launch_Q2_Read', options = dict(pos_x = '-3.5mm', orientation = '0'))\n",
    "\n",
    "launch_Q1_cl = LaunchpadWirebond(design, 'Launch_Q1_CL', options = dict(pos_x = '1.35mm', pos_y = '-2.5mm', orientation = '90'))\n",
    "launch_Q2_cl = LaunchpadWirebond(design, 'Launch_Q2_CL', options = dict(pos_x = '-1.35mm', pos_y = '2.5mm', orientation = '-90'))\n",
    "\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tl_Q1 = RoutePathfinder(design, 'TL_Q1', options = dict(\n",
    "                                            fillet='99um',\n",
    "                                            lead=dict(end_straight='150um'),\n",
    "                                            pin_inputs=Dict(\n",
    "                                                start_pin=Dict(\n",
    "                                                    component='Launch_Q1_Read',\n",
    "                                                    pin='tie'),\n",
    "                                                end_pin=Dict(\n",
    "                                                    component='Cap_Q1',\n",
    "                                                    pin='b')\n",
    "                                            )))\n",
    "\n",
    "tl_Q2 = RoutePathfinder(design, 'TL_Q2', options = dict(\n",
    "                                            fillet='99um',\n",
    "                                            lead=dict(end_straight='150um'),\n",
    "                                            pin_inputs=Dict(\n",
    "                                                start_pin=Dict(\n",
    "                                                    component='Launch_Q2_Read',\n",
    "                                                    pin='tie'),\n",
    "                                                end_pin=Dict(\n",
    "                                                    component='Cap_Q2',\n",
    "                                                    pin='b')\n",
    "                                            )))\n",
    "\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tl_Q1_cl = RoutePathfinder(design, 'TL_Q1_CL', options = dict(\n",
    "                                            fillet='99um',\n",
    "                                            lead=dict(end_straight='150um'),\n",
    "                                            pin_inputs=Dict(\n",
    "                                                start_pin=Dict(\n",
    "                                                    component='Launch_Q1_CL',\n",
    "                                                    pin='tie'),\n",
    "                                                end_pin=Dict(\n",
    "                                                    component='Q1',\n",
    "                                                    pin='Charge_Line')\n",
    "                                            )))\n",
    "\n",
    "tl_Q2_cl = RoutePathfinder(design, 'TL_Q2_CL', options = dict(\n",
    "                                            fillet='99um',\n",
    "                                            lead=dict(end_straight='150um'),\n",
    "                                            pin_inputs=Dict(\n",
    "                                                start_pin=Dict(\n",
    "                                                    component='Launch_Q2_CL',\n",
    "                                                    pin='tie'),\n",
    "                                                end_pin=Dict(\n",
    "                                                    component='Q2',\n",
    "                                                    pin='Charge_Line')\n",
    "                                            )))\n",
    "\n",
    "gui.rebuild()\n",
    "gui.autoscale()\n",
    "gui.screenshot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Simulation and Analysis\n",
    "\n",
    "With our fully designed chip now laid out, we can start to focus on tuning the components to hit the circuit parameters we are interested in. These will tend to be;\n",
    "- qubit: frequency, the anharmonicity/alpha, and the coupling strength (as chi, g, or other)\n",
    "- busses: frequency (if resonant), the coupling strength\n",
    "- readout: frequency, coupling strength, coupling to external lines (as kappa, Q_external, or other)\n",
    "\n",
    "### Analysis via capacitance matrix and LOM\n",
    "\n",
    "All of the qubit paramters can initially be tuned via a capacitance matrix and the lumped oscillator method. This analysis is not as accurate as others, but allows for fairly fast and small simulations.\n",
    "\n",
    "We will start by selecting the Analysis class of interest."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit_metal.analyses.quantization import LOManalysis\n",
    "c1 = LOManalysis(design, \"q3d\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can see what options are available for the analysis and make any changes we may wish, such as increasing the buffer size for the bounding box when simulation subsections of the chip."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sim_p = c1.sim.setup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sim_p.name = 'QubitTune'\n",
    "sim_p.max_passes = 15\n",
    "sim_p.min_converged_passes = 2\n",
    "sim_p.percent_error = 0.1\n",
    "\n",
    "c1.sim.setup"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "With the design and simulation setup, we render the qubit. For LOM analysis, we want the connection pads to be terminated with opens. We indicate this by stating which unconnected pins should have open terminations.\n",
    "\n",
    "*During the execution of the next cell, make sure to deal with any pop up boxes from Ansys as it opens up (if it was closed)*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "c1.sim.run(name=\"Qubit1\", components=['Q1'], open_terminations=[('Q1', 'readout'), ('Q1', 'bus')])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Once complete, we can grab the capacitance matrix (next cell) and/or (following cells) call on an LOM analysis of the simulation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "c1.sim.capacitance_matrix"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "c1.setup.junctions = Dict({'Lj': 14, 'Cj': 2})\n",
    "c1.setup.freq_readout = 7.0\n",
    "c1.setup.freq_bus = [0.1, 0.1]  # list of the bus frequencies\n",
    "\n",
    "c1.run_lom()\n",
    "c1.lumped_oscillator_all"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can finally observe how the main quantum parameters have converged after the previous simulation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "c1.plot_convergence();\n",
    "c1.plot_convergence_chi()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that it is possible for a (physically) converged simulation, to not have quite converged in the quantum realm.\n",
    "\n",
    "Looking at the convergence plots from the previous cell, we can see that we did not have enough passes for the simulation. In this case, we want to modify our simulation setup, 'QubitTune', to improve our convergence (increase number of passes, or changing some other parameters)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Once we will know that simulation has converged, we can use those results to make appropriate changes to our qubit layout. Say our anharmonicity/alpha is higher than we want? Since we know Ec~ 1/C, we can change parts of the transmon pocket to lower the total capacitance seen across the junction.\n",
    "If g to the bus is too low, we can increase the width of the connection pad so that the capacitance between the connection pad and charge island is greater.\n",
    "\n",
    "One must also keep in mind that any such changes will impact the other parameters, so careful tweaks and iterations of simulation/analysis often end up being necessary.\n",
    "\n",
    "If wanting to make changes and re-render your design, you first should clear your current design."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "c1.sim.renderer.clean_active_design()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "When done with all the simulations, you can disconnect from Ansys EDT."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "c1.sim.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Analysis via eigenmode and EPR"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, although the previous simulation and analysis captured all of the parameters of the qubits and coupling to the bus, a more accurate (all be it slower) approach is to render the qubits and their coupling into an eigenmode simulation and perform EPR analysis on the result.\n",
    "\n",
    "We again start by selecting the Analysis class of interest."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit_metal.analyses.quantization import EPRanalysis\n",
    "eig_qb = EPRanalysis(design, \"hfss\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Review and update the simulation setup by executing following two cells."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "em_p = eig_qb.sim.setup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "em_p.name = 'QubitTune'\n",
    "em_p.min_freq_ghz = 3\n",
    "em_p.n_modes = 2\n",
    "em_p.max_passes = 12\n",
    "em_p.max_delta_f = 0.1\n",
    "em_p.min_converged = 2\n",
    "# Design variables can also be added in for direct simulation sweeps.\n",
    "em_p.vars = Dict({'Lj1': '14 nH', 'Cj1': '0 fF', 'Lj2': '12 nH', 'Cj2': '0 fF'})\n",
    "\n",
    "eig_qb.sim.setup"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can now run the simulation on the specified layout."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_qb.sim.run(name=\"Q1_Q2_Bus\", components=['Bus_Q1_Q2', 'Q1', 'Q2'], open_terminations=[])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Once completed, we can check the convergence to see if more passes might be necessary."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_qb.sim.plot_convergences()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This eigenmode simulation is also a quick method to check for any bus or readout resonator frequencies. \n",
    "If happy with the simulation, we can then jump to some EPR analysis.\n",
    "\n",
    "At first we need to define the junctions in terms of name, inductance_variable, capacitance_variable, rectancle that was defined in the rendering to represent the junction `port` and line that was defined in the rendering to represent the direction of the current thorugh the junction."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_qb.del_junction()\n",
    "eig_qb.add_junction('jj1', 'Lj1', 'Cj1', rect='JJ_rect_Lj_Q1_rect_jj', line='JJ_Lj_Q1_rect_jj_')\n",
    "eig_qb.add_junction('jj2', 'Lj2', 'Cj2', rect='JJ_rect_Lj_Q2_rect_jj', line='JJ_Lj_Q2_rect_jj_')\n",
    "eig_qb.setup.sweep_variable = 'Lj1'\n",
    "eig_qb.setup"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note in the previous cell output that the dissipatives have alrady been defined by default.\n",
    "\n",
    "Now we can start looking at the EPR values. First we look at the electric field and subtrate participation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_qb.run_epr()\n",
    "# (pyEPR allows to switch modes: eprd.set_mode(1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "From the analysis results we can determine the qubits anharmonicities and coupling strength."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Other analysis is still being added, such as the impedance analysis, though some already be done manually by renderering to a driven modal simulation and performing frequency sweeps to extract the S-Parameters or Impedance matrix. This would be an easy way to, say, determine the external quality factor of a readout resonator. *See tutorial notebooks 4.3*\n",
    "\n",
    "Once the analysis and tuning is complete, we can disconnect from the renderer."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_qb.sim.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Rendering to a GDS File"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Once all of the tuning is complete, we will want to prepare a GDS file so we can create a mask and fabricate our chip. We first create a gds render instance."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "qhk21_gds = design.renderers.gds"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The various options for the gds renderer can be checked and changed as necessary. A key option is the gds file which holds the cells for your junction ebeam design. Make sure this is pointing at the correct file so they are placed in your final mask at the appropriate locations."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "qhk21_gds.options"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "qhk21_gds.options['path_filename'] = '../resources/Fake_Junctions.GDS'\n",
    "qhk21_gds.options['no_cheese']['buffer']='50um'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "qhk21_gds.export_to_gds('QHK21_Tutorial.gds')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "(optional) Now that the design is finished, we can close the GUI."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# gui.main_window.close()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
